﻿using Jermaine.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;

namespace Jermaine.Extensions
{
    public enum TargetType
    {
        Porperty,
        Field
    }

    public static class ObjectExtensions
    {
        #region Getter
        public static T Get<T>(this Object o, int index, TargetType targetType = TargetType.Porperty) {
            return targetType == TargetType.Porperty ?
                Reflector.GetPropertyValue<T>(o, index) :
                Reflector.GetFieldValue<T>(o, index);

        }

        public static T Get<T>(this Object o, string key) {
            var prop = Reflector.GetProperty(o.GetType(), key);
            if (prop != null) {
                return Reflector.GetPropertyValue<T>(o, key);
            }

            var field = Reflector.GetField(o.GetType(), key);
            if (field != null) {
                return Reflector.GetFieldValue<T>(o, key);
            }
            return default(T);
        }
        #endregion

        #region Setter
        public static void Set<T>(this Object o, int index, T value, TargetType targetType = TargetType.Porperty) {
            if (targetType == TargetType.Porperty) {
                Reflector.SetPropertyValue<T>(o, index, value);
            } else {
                Reflector.SetFieldValue<T>(o, index, value);
            }
        }

        public static void Set<T>(this Object o, string key, T value) {
            var prop = Reflector.GetProperty(o.GetType(), key);
            if (prop != null) {
                Reflector.SetPropertyValue<T>(o, key, value);
                return;
            }

            var field = Reflector.GetField(o.GetType(), key);
            if (field != null) {
                Reflector.SetFieldValue<T>(o, key, value);
            }

        }

        #endregion

        #region Invoker
        public static T Fire<T>(this Object o, string methodName, params Object[] args) {
            return Reflector.Call<T>(o, methodName, args);
        }

        public static void Fire(this Object o, string methodName, params Object[] args) {
            Reflector.Call(o, methodName, args);
        }

        public static T Fire<T>(this Object o, int index, params Object[] args) {
            return Reflector.Call<T>(o, index, args);
        }

        public static void Fire(this Object o, int index, params Object[] args) {
            Reflector.Call(o, index, args);
        }

        #endregion
    }
}
